#ifndef DATABASE_H
#define DATABASE_H

#include <QtCore/QMap>
#include <QtCore/QStringList>
#include <QtCore/QDateTime>
#include <QtCore/QMetaType>

namespace acidone
{

class Subject
{
public:
	explicit Subject(const QString& name);
	QString name() const;
	void setName(const QString& name);

private:
	QString m_name;
};

class Category
{
public:
	explicit Category(const QString& name);
	QString name() const;
	void setName(const QString& name);

private:
	QString m_name;
};

class Task : public QObject
{
	Q_OBJECT
public:
	/// Приоритет задачи
	enum Priority
	{
		Low,
		Normal,
		High,
	};

	explicit Task(QObject* parent = 0);

	/// Возвращает список категорий этой задачи
	QList<Category*> categories() const;
	void setCategories(QList<Category*> categories);
	void setSingleCategory(Category* category);

	void addCategory(Category* category);
	void removeCategory(Category* category);

	/// Возвращает тему
	QString caption() const;
	void setCaption(const QString& caption);

	/// Возвращает дату начала
	QDateTime beginDateTime() const;
	void setBeginDateTime(const QDateTime& beginDateTime);
	bool isStarted() const;

	/// Возвращает дату к которой задача должна быть завершена
	QDateTime endDateTime() const;
	void setEndDateTime(const QDateTime& endDateTime);

	/// Возвращает приоритет задачи
	Priority priority() const;
	void setPriority(Priority priority);

	/// Возвращает текстовые заметки к задаче
	QString notes() const;
	void setNotes(const QString& notes);

	/// Возвращает идентификатор субъекта, ответсвенного за задачу
	Subject* subject() const;
	void setSubject(Subject* subject);

	QDateTime creationDateTime() const;
	void setCreationDateTime(const QDateTime& dateTime);

	bool isCompleted() const;
	void complete();
	void setCompletionDateTime(const QDateTime& dateTime);
	QDateTime completionDateTime() const;

signals:
	void changed();

private:
	typedef QList<Category*> Categories;

	Categories m_categories;
	QString m_caption;
	QDateTime m_beginDateTime;
	QDateTime m_endDateTime;
	Priority m_priority;
	QString m_notes;
	Subject* m_subject;

	QDateTime m_creationDateTime;
	QDateTime m_completionDateTime;
};

class Database : public QObject
{
	Q_OBJECT
public:

	typedef QList<Task*> TaskList;
	typedef QList<Category*> Categories;
	typedef QList<Subject*> Subjects;

	explicit Database(QObject* parent = 0);
	~Database();

	// Список задач
	void addTask(Task* task);
	void removeTask(Task* task);

	TaskList tasks() const;
	/// Возвращает все задачи по категории
	TaskList tasksByCategory(Category* category) const;
	TaskList tasksBySubject(Subject* subject) const;

	template<typename _Pred>
		TaskList tasksByCondition(_Pred pred) const
	{
		TaskList res;
		foreach(Task* task, m_tasks)
			if (pred(*task))
				res.append(task);
		return res;
	}

	// Список категорий
	/// Добавить категорию. Возвращает id добавленной категории.
	Category* addCategory(const QString& name);
	Category* findCategory(const QString& name);

	/// Удалить категорию по id
	void removeCategory(Category* id);

	Categories categories() const;

	/// Возвращает названия всех категорий
	QStringList categoryNames() const;

	// Список субъектов
	Subject* addSubject(const QString& name);
	Subject* findSubject(const QString& name);

	void removeSubject(Subject* subject);

	Subjects subjects() const;

	QStringList subjectNames() const;

signals:
	void changed();

private:

	Categories m_categories;
	Subjects m_subjects;
	TaskList m_tasks;
};

}

Q_DECLARE_METATYPE(acidone::Subject*);
Q_DECLARE_METATYPE(acidone::Category*);
Q_DECLARE_METATYPE(acidone::Task*);

#endif // DATABASE_H
